package com.tc.entity;

/**
 * Created by cai.tian on 2017/12/11.
 */
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;


public class RestApiControllerHandlerMapping extends RequestMappingHandlerMapping {

    private final static String MAPPING_URL = "mapping.url";

    private static final String WEB_MODULE_NAME = "com.vip.venus_venus-web_venus-web.module";

    private Map<String, String> mappings = new HashMap<String, String>();

    private Map<String, String> mappingUrlMap = new LinkedHashMap<String, String>();

    /**
     * set some custom mapping
     * @param patternMap
     */
    public void setMappings(Map<String, String> patternMap) {
        this.mappings = patternMap;
    }

    public RestApiControllerHandlerMapping() {
        registerMapping();
    }

    private void registerMapping() {
        Map<String, Object> values = new LinkedHashMap<String, Object>();
        values.put(MAPPING_URL, mappingUrlMap);

        //MetricRegister.registerInternal(values, WEB_MODULE_NAME);
    }

    /**
     * Detects {@code @FrameworkController} annotations in handler beans.
     *
     * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#isHandler(java.lang.Class)
     */
    @Override
    protected boolean isHandler(Class<?> beanType) {
        return AnnotationUtils.findAnnotation(beanType, RestApiController.class) != null;
    }

    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo defaultMapping = super.getMappingForMethod(method, handlerType);
        if (null == defaultMapping) {
            return null;
        }

        Set<String> defaultPatterns = defaultMapping.getPatternsCondition().getPatterns();
        String[] patterns = new String[defaultPatterns.size()];

        String methodType = RequestMethod.GET.toString();
        Set<RequestMethod> requestMethods = defaultMapping.getMethodsCondition().getMethods();
        if (requestMethods != null && requestMethods.size() > 0) {
            RequestMethod requestMethod = requestMethods.iterator().next();
            if (requestMethod != null) {
                methodType = requestMethod.toString();
            }
        }

        // replace as custom mapping
        int i = 0;
        for (String pattern : defaultPatterns) {
            patterns[i] = pattern;
            if (mappings.containsKey(pattern)) {
                patterns[i] = mappings.get(pattern);
            }
            i++;

            mappingUrlMap.put(pattern + ":" + methodType, methodType);
        }

        PatternsRequestCondition patternsInfo = new PatternsRequestCondition(patterns);

        ParamsRequestCondition paramsInfo = defaultMapping.getParamsCondition();

        RequestMappingInfo mapping = new RequestMappingInfo(patternsInfo, defaultMapping.getMethodsCondition(),
                paramsInfo, defaultMapping.getHeadersCondition(), defaultMapping.getConsumesCondition(),
                defaultMapping.getProducesCondition(), defaultMapping.getCustomCondition());
        return mapping;

    }
}